<?php

namespace app\common\services;

use app\admin\app\servicers\BaseService;
use support\Db;
use support\exception\ApiException;
use support\Request;

class DragdoneUpService extends BaseService
{
    const sortSpace = 1000;// 排序默认间距

    /**
     * 拖拽排序 后台处理逻辑
     * @param Request $request 接收的参数
     * @param \support\Model $model 被排序的表
     * @return true
     * @throws ApiException
     */
    static function dragDoneUpData(Request $request,\support\Model $model){
        $primary_key = $model->getKeyName();
        // 获取前一条数据的 排序数值
        $params = $request->post();
        $field = $params['field'];
        $selfId = $params[$primary_key];
        $afterWeight = $beforWeight = 0;
        if($params['beforId']){
            $beforWeight = $model->where($primary_key,$params['beforId'])->value($field);
        }else{
            // 不存在 则查询 后一个位置的前一条记录  先查询 后者的排序值
            $afterWeight = $model->where($primary_key,$params['afterId'])->value($field);

            $info = $model->where([[$field,'>',$afterWeight],[$primary_key,'<>',$selfId]])->orderBy($field,'desc')->select($primary_key,$field)->first();
            if($info){
                $beforWeight = $info[$field];
                $params['beforId'] = $info[$primary_key];
            }else{
                $beforWeight = -1 ;// 没有记录
            }
        }
//        Logger::debug(['$beforWeight',$beforWeight]);
        if(!$afterWeight){
            if($params['afterId']){
                $afterWeight = $model->where($primary_key,$params['afterId'])->value($field);
            }else{
                $info = $model->where([[$field,'<',$beforWeight],[$primary_key,'<>',$selfId]])->orderBy($field,'desc')->select($primary_key,$field)->first();
                if($info){
                    $afterWeight = $info[$field];
                    $params['afterId'] = $info[$primary_key];
                }else{
                    $afterWeight = -1 ;// 没有记录
                }
            }
        }

        // 间隔值太小  触发全表重排
        if(abs($afterWeight - $beforWeight)<10  ||
            ($beforWeight<0 && $afterWeight<10) ||
            ($beforWeight<10 && $afterWeight<0)
        ){
            self::dragDoneUpDataDefault($model,$field);
            // 再次获取新的 排序数值
            $beforWeight = $model->where($primary_key,$params['beforId'])->value($field)?:-1;
            $afterWeight = $model->where($primary_key,$params['afterId'])->value($field)?:-1;
        }

        // 如果当前位置末尾没有数据了
        if($afterWeight == -1) $afterWeight = 0;
        if($beforWeight == -1){
            // 如果当前位置前面没有数据了  则更新的排序值 = 最大的排序值+间隔值
            $newWeight = $afterWeight + self::sortSpace;
        }else{
            // 取中间值 则为当前数据的值
            $newWeight = ceil(($beforWeight + $afterWeight) / 2);
        }
//        Logger::debug(['取中间值',$newWeight,$beforWeight,$afterWeight,$params]);
        if($newWeight<2){
//            throw new ApiException('抱歉，排序失败，取值错误');
        }
        // 更新排序
        $model->where($primary_key,$selfId)->update([$field=>$newWeight]);
        return $newWeight;
    }

    /**
     * 全表重排排序
     * @param \support\Model $model
     * @param $field
     * @param $sortSpace
     * @return void
     */
    static protected function dragDoneUpDataDefault(\support\Model $model,$field){
        $tableName = $model->getTable();
        $primary_key = $model->getKeyName();
        $sortSpace = self::sortSpace;
        DB::statement("SET @row_number = 0");
        $sql = " UPDATE $tableName t1
                JOIN (
                    SELECT id, (@row_number := @row_number + 1) AS new_weight
                    FROM (
                        SELECT id, $field
                        FROM $tableName
                        ORDER BY $field asc,$primary_key asc
                    ) AS sorted_table
                ) AS t2 ON t1.id = t2.id
                SET t1.$field = t2.new_weight * $sortSpace";
        return Db::statement($sql);
    }
}